package customer

import (
	"context"
	"fmt"
	"go.manyji.com/lib/encoding/json"
	"go.manyji.com/lib/log"
	"go.manyji.com/lib/util/errors"
	"sieve_admin_server/app/dao/business_type"
	"sieve_admin_server/app/dao/sieve_config"
	"sieve_admin_server/app/schema"
	schemaCustomer "sieve_admin_server/app/schema/customer"
	"sieve_admin_server/pkg/slice"
	"strings"
	"sync"
	"time"
)

var (
	businessTypeCronOnce = sync.Once{}
	initBizFinished      bool
)

func (a *BusinessTypeSrv) init() error {

	var (
		initCount = 2
		wp        = sync.WaitGroup{}
		logMsg    []string
	)

	wp.Add(initCount)
	go func() {
		a.WaitFinished()
		err := a.initSysBusinessPrices()
		logMsg = append(logMsg, fmt.Sprintf("%+v", err))
		wp.Done()
	}()

	go func() {
		a.UserAuthSrv.WaitFinished()
		err := a.initSysBusinessType()
		logMsg = append(logMsg, fmt.Sprintf("%+v", err))
		initBizFinished = true
		wp.Done()
	}()

	wp.Wait()

	return errors.New(strings.Join(logMsg, ","))
}

func (a *BusinessTypeSrv) WaitFinished() {

	for !initBizFinished {
		time.Sleep(time.Millisecond * 10)
	}
}

func (a *BusinessTypeSrv) Cron() error {

	businessTypeCronOnce.Do(func() {
		log.Info(fmt.Sprintf("%v", a.init()))
	})

	return nil
}

func (a *BusinessTypeSrv) initSysBusinessPrices(args ...interface{}) error {

	var (
		ctx     = context.Background()
		reqArgs = map[string]interface{}{
			"role_id":                a.RoleSrv.GetAdminRole().ID,
			"sieve_source_config_id": 0,
			"status":                 1,
		}
		p = schema.PaginationParam{
			OnlyData: true,
		}
		repKeys = []string{"*"}
	)
	ctx = context.WithValue(ctx, "condition", map[string]string{
		"sieve_source_config_id": ">",
	})

	resp := a.QueryTypes(ctx, reqArgs, p, repKeys)
	if resp == nil {
		return nil
	}

	if _, ok := resp.(error); ok {
		log.Err(fmt.Sprintf("获取业务类型配置失败:%+v", resp.(error)))
		return nil
	}
	var (
		name2Price = map[string]uint64{}
		vData      []schemaCustomer.BusinessTypeQueryRsp
	)
	if v1, ok := resp.(map[string]interface{}); ok {
		for _, v2 := range v1["list"].([]interface{}) {
			item := v2.(*business_type.BusinessTypeConfiguration)

			vData = append(vData, schemaCustomer.BusinessTypeQueryRsp{
				Name:      item.Name,
				UnitPrice: item.UnitPrice,
			})
			name2Price[item.Name] = item.UnitPrice
		}
	}

	b, _ := json.Marshal(vData)
	priceStr := json.RawMessage(b)
	item := map[string]interface{}{
		"name":        "系统默认方案",
		"description": "系统默认方案",
		"def":         uint64(1),
		"prices":      string(priceStr),
	}
	if respDef := a.BusinessPriceSrv.Query(ctx, int(adminAccount.ID), map[string]interface{}{
		"def": 1,
	}, schema.PaginationParam{OnlyData: true}); respDef == nil {
		log.Info(fmt.Sprintf("创建默认价格方案的结果:%v", a.BusinessPriceSrv.Create(ctx, int(adminAccount.ID), item)))
	} else {
		if err, ok := respDef.(error); ok {
			return err
		}
		defItems := respDef.(map[string]interface{})["list"].([]interface{})
		if len(defItems) <= 0 {
			//log.Err(fmt.Sprintf("没有默认价格方案"))
			//return stdErrors.New(fmt.Sprintf("没有默认价格方案"))
			log.Info(fmt.Sprintf("创建默认价格方案的结果:%v", a.BusinessPriceSrv.Create(ctx, int(adminAccount.ID), item)))
		}
		respData := defItems[0].(*schemaCustomer.BusinessPriceQueryRsp)
		id := respData.ID
		prices := respData.Prices

		var vv []schemaCustomer.BusinessTypeQueryRsp
		if err := json.Unmarshal(prices, &vv); err != nil {
			return err
		} else {
			respDetails := vv

			var needUpdate bool
			if len(respDetails) != len(name2Price) {
				needUpdate = true
			} else {
				for _, v := range respDetails {
					itemData := v

					if vv, ok := name2Price[itemData.Name]; ok {
						if vv != itemData.UnitPrice {
							needUpdate = true
						}
					} else {
						needUpdate = true
					}
					if needUpdate {
						break
					}
				}
			}

			if needUpdate {
				updateItem := map[string]interface{}{
					"id":          id,
					"name":        respData.Name,
					"description": respData.Description,
					"def":         uint64(1),
					"prices":      string(priceStr),
				}

				if err := a.BusinessPriceSrv.Update(ctx, int(adminAccount.ID), updateItem); err != nil {
					log.Info(fmt.Sprintf("更新默认价格方案发生错误:%+v", err))
				}
			}
		}
	}
	return nil
}

func (a *BusinessTypeSrv) initSysBusinessType(args ...interface{}) error {

	var (
		entity   = business_type.BusinessTypeConfiguration{}
		querySQL = fmt.Sprintf(`
		SELECT
			*
		FROM
		    business_type_configuration
		WHERE
		    creator = %v
`, adminAccount.ID)
	)

	req, err := a.BusinessTypeRepo.QueryRaw(context.Background(), querySQL, entity)
	if err != nil {
		log.Err("query business type configuration err:%+v", err)
		return err
	}

	var (
		sliceB      []string
		sliceA      []string
		mapA        = make(map[string]*business_type.BusinessTypeConfiguration)
		mapB        = make(map[string]*business_type.BusinessTypeConfiguration)
		updateItems []map[string]interface{}
		insertItems []map[string]interface{}
		deleteItems []string
	)

	for _, s := range bizConfig {
		sliceA = append(sliceA, fmt.Sprintf("%v", s.Name))
		vCopy := s
		vCopy.Creator = int64(adminAccount.ID)
		vCopy.RoleId = uint64(adminAccount.RoleId)
		mapA[s.Name] = vCopy
	}

	for _, s := range req {

		respBiz := s.(*business_type.BusinessTypeConfiguration)
		sliceB = append(sliceB, fmt.Sprintf("%v", respBiz.Name))
		mapB[respBiz.Name] = respBiz
	}

	// 1. 取交集
	for _, ss := range slice.Intersect(sliceA, sliceB) {

		if v, ok := mapA[ss]; ok {
			//if v.Desc == mapB[ss].Desc && v.UnitPrice == mapB[ss].UnitPrice && v.RoleId == mapB[ss].RoleId && v.Creator == mapB[ss].Creator {
			//	continue
			//}

			if v.UnitPrice == mapB[ss].UnitPrice {
				continue
			}
			updateItems = append(updateItems, map[string]interface{}{
				"unit_price": v.UnitPrice,
				"desc":       v.Desc,
				"role_id":    v.RoleId,
				"creator":    v.Creator,
			})
		}
	}

	// 2. 取差集(源数据有，而表没有) 需要插入到搜索表
	for _, ss := range slice.Difference(sliceA, sliceB) {

		if v, ok := mapA[ss]; ok {
			insertItems = append(insertItems, map[string]interface{}{
				"name":       v.Name,
				"unit_price": v.UnitPrice,
				"desc":       v.Desc,
				"role_id":    v.RoleId,
				"creator":    v.Creator,
			})
		}
	}

	// 3. 取差集(表有，而源数据没有) 需要删除表
	//for _, ss := range slice.Difference(sliceB, sliceA) {
	//
	//	if v, ok := mapB[ss]; ok {
	//		deleteItems = append(deleteItems, fmt.Sprintf("%v", v.ID))
	//	}
	//}

	//for _, v := range updateItems {
	//	if err := a.BusinessTypeSrv.Update(context.Background(), int(adminAccount.ID), v); err != nil {
	//		log.Err(fmt.Sprintf("更新业务类型配置错误%+v", err))
	//	}
	//}
	var dscId uint64
	if rsp := a.SieveConfigSrv.Query(context.Background(), map[string]interface{}{
		"default": 1,
	}, schema.PaginationParam{}, []string{"*"}); rsp != nil {
		if _, ok := rsp.(map[string]interface{}); ok {
			if len(rsp.(map[string]interface{})["list"].([]interface{})) != 0 {
				dscId = uint64(rsp.(map[string]interface{})["list"].([]interface{})[0].(*sieve_config.SieveSourceConfig).ID)
			}
		}
	}
	for _, v := range insertItems {
		v["sieve_source_config_id"] = uint64(dscId)
		if err := a.Create(context.Background(), int(adminAccount.ID), v); err != nil {
			log.Err(fmt.Sprintf("更新业务类型配置错误%+v", err))
		}
	}

	if len(deleteItems) > 0 {
		var (
			deleteSQL = fmt.Sprintf(`
			DELETE FROM %v
			WHERE id IN (%v)
`, business_type.BusinessTypeConfiguration{}.TableName(), strings.Join(deleteItems, ","))
		)
		if _, err := a.BusinessTypeRepo.ExecRaw(context.Background(), deleteSQL); err != nil {
			log.Err("delete menus err:%+v", err)
			return err
		}
	}

	return nil
}
